import EventManager from "./eventManager";
import NodePool from "./NodePool";
import Events from "./events";

const {
    ccclass,
    property
} = cc._decorator;

let FILTER_LIST = {
    wait_layer: true,
    msg_layer: true,
}
/**
 * 层级管理
 */
@ccclass
export default class LayerManager extends cc.Component {
    @property
    sceneName: string = '';
    @property([cc.Prefab])
    preloadLayer: cc.Prefab[] = [];

    private _showList: any = {};
    private _showArr: cc.Node[] = [];
    private _loadingList: any = {};
    private _layerPool: any = null;
    private _basePath: string = '';

    onLoad() {
        this.addEvent();
        this.dataInit();
    }
    onDestroy() {
        this.removeEvent();
        this._layerPool.clearAll();
    }

    addEvent() {
        EventManager.registerHandler(Events.OPEN_LAYER, this);
        EventManager.registerHandler(Events.CLOSE_LAYER, this);
        EventManager.registerHandler(Events.CLOSE_ALL_LAYER, this);
        EventManager.registerHandler(Events.CLOSE_LAYER_WITH_ID, this);
    }

    removeEvent() {
        EventManager.removeHandler(Events.OPEN_LAYER, this);
        EventManager.removeHandler(Events.CLOSE_LAYER, this);
        EventManager.removeHandler(Events.CLOSE_ALL_LAYER, this);
        EventManager.removeHandler(Events.CLOSE_LAYER_WITH_ID, this);
    }

    dataInit() {
        this._showList = {};
        this._showArr = [];
        this._loadingList = {};
        this._layerPool = new NodePool();
        this._basePath = '/prefab';
        this.preloadlayer();
    }

    /**
     * @description 预加载layer
     */
    preloadlayer() {
        for (let i = 0; i < this.preloadLayer.length; i++) {
            let node = cc.instantiate(this.preloadLayer[i]);
            this._layerPool.put(node, node.name);
        }
    }

    /**
     * @description layer节点添加到显示列表
     * @param node 
     * @param nodeParent 
     * @param id 
     */
    private _addShowList(node, nodeParent, id) {
        if (!this.node) {
            //自身场景已经被销毁 显示终止
            node.destroy();
            return;
        }
        node.parent = nodeParent;
        node.active = true;
        node.setPosition(cc.v2(0, 0));
        if (this._showList[id]) {
            this._showList[id].destroy();
            console.error("显示界面重复", id);
        }
        this._showList[id] = node;
        this._showArr.push(node);
        delete this._loadingList[id];
    }

    /**
     * @description 从显示列表中移除layer
     * @param id 
     */
    private _removeShowList(id) {
        delete this._showList[id];
        for (let i = 0; i < this._showArr.length; i++) {
            if (this._showArr[i].name == id) {
                this._showArr.splice(i, 1);
                i--;
            }
        }
    }

    /**
     * @description 打开layer
     * @param layerId 
     * @param layerParent 
     */
    private _openLayer(layerId, layerParent) {
        if (this._showList[layerId] || this._loadingList[layerId]) return;
        this._loadingList[layerId] = true;
        this._showLayer(layerId, layerParent);
    }

    /**
     * @description 显示layer
     * @param layerId 
     * @param layerParent 
     */
    private _showLayer(layerId, layerParent) {
        let self = this;
        let path = this._loadPathDispose(layerId);
        let node = this._layerPool.get(layerId);
        if (!node) {
            cc.loader.loadRes(path, cc.Prefab, function (err, res) {
                if (res) {
                    node = cc.instantiate(res);
                    self._addShowList(node, layerParent, layerId);
                    cc.loader.setAutoRelease(path, true);
                }
            })
        } else {
            this._addShowList(node, layerParent, layerId);
        }
    }

    /**
     * @description 关闭layer
     * @param layerId 
     * @param isDestroy 
     */
    private _closeLayer(layerId, isDestroy: boolean = false) {
        let layer = this._showList[layerId];
        if (!layer) return;
        this._removeShowList(layerId);
        if (isDestroy) {
            layer.destroy();
        } else {
            this._layerPool.put(layer, layer.name);
        }
    }

    /**
     * @description 关闭最上层layer
     */
    private _closeNowLayer() {
        let close_id;
        let show_layer_num = this._showArr.length;
        if (show_layer_num) {
            close_id = this._showArr[show_layer_num - 1].name;
            this._closeLayer(close_id);
        }
    }

    /**
     * @description 关闭所有layer
     */
    private _closeAllLayer() {
        for (let i in this._showList) {
            this._closeLayer(i);
        }
    }

    /**
     * @description 处理加载路径
     * @param layerId 
     */
    private _loadPathDispose(layerId) {
        let sceneName = this.sceneName;
        let path = FILTER_LIST[layerId] ?
            this._basePath + layerId : this._basePath + sceneName + '/' + layerId;
        return path;
    }

    /**
     * @description 每帧处理layer事件
     * @param event 
     */
    processEvent(event) {
        var msgId = event['msgId'];
        switch (msgId) {
            case Events.OPEN_LAYER: 
                let layerParent = event['layerParent'] ? event['layerParent'] : cc.find("Canvas");
                this._openLayer(event['layerId'], layerParent);
                break;
            case Events.CLOSE_LAYER: 
                this._closeNowLayer();
                break;
            case Events.CLOSE_ALL_LAYER:
                this._closeAllLayer();
                break;
            case Events.CLOSE_LAYER_WITH_ID:
                this._closeLayer(event['layerId'], event['destroy']);
                break;
            }
    }
}